#include "Assign.h"
#include "../Exceptions.h"
#include "../GeneralVisitor.h"

Assign::Assign(TreeNode* iVariable, TreeNode* iExpression)
{
    this->fVariable = iVariable;
    this->fExpression = iExpression;
    this->fVariable->SetLeftValue();
}

Assign::~Assign()
{
    delete this->fVariable;
    delete this->fExpression;
}

void Assign::CheckVariables(set<string>& oVariables, string iParentName)
{
    this->fVariable->CheckVariables(oVariables, iParentName);
}

void Assign::CheckFunctionCalls(set<FunctionDefinition*>& iAllFunctions, string iParentName)
{
    this->fExpression->CheckFunctionCalls(iAllFunctions, iParentName);
}

void Assign::CheckClassConstructions(set<ClassDefinition*>& iAllClasses, string iParentName)
{
    this->fExpression->CheckClassConstructions(iAllClasses, iParentName);
}

void Assign::CheckExpressionTypes(map<string, ExpressionType*>& iVarTypes, string iParentName)
{
    // pokud je to pristup k fieldu, tak tam se zjisti (mozna), jestli ten field existuje
    this->fVariable->CheckExpressionTypes(iVarTypes, iParentName);

    // pokud je to obycejna promenna, aktualizuju ji typ...
    // ... u prirazovani k fieldum trid to delat nebudu, bylo by to moc slozity
    // ... ani pokud prirazuju neco do pole
    if(!this->fVariable->IsClassField() && !this->fVariable->IsArrayAccess())
    {
        ExpressionType* lType = this->fExpression->GetType(iVarTypes, iParentName);
        string lVarName = this->fVariable->GetVarName();

        // coze? to by se stat nemelo... to uz melo byt osetrene...
        if(iVarTypes.find(lVarName) == iVarTypes.end())
        {
            delete lType;
            throw VariableNotDeclaredException(iParentName, lVarName);
        }

        iVarTypes[lVarName]->UpdateValuesAndDiscardParam(lType);
    }
}

void Assign::Accept(GeneralVisitor* iVisitor)
{
    iVisitor->Visit(this);
}